#include <iostream>
using namespace std;
#include <string>
#include <sys/epoll.h>
#include <unistd.h>
#include "Sock.hpp"

#define SIZE 128
#define NUM 64

void Usage(const string &proc)
{
    cout << "Usage: " << proc << " port " << endl;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
    }
    // 创建监听
    int listen_sock = Sock::Socket();
    uint16_t port = atoi(argv[1]);
    Sock::Bind(listen_sock, port);
    Sock::Listen(listen_sock);
    // 创建epoll
    int epfd = epoll_create(SIZE);
    epoll_event revs[NUM];
    epoll_event _ev;
    _ev.events = EPOLLIN;
    _ev.data.fd = listen_sock;
    // 将监听sock放入epoll
    epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sock, &_ev);
    // 执行业务逻辑
    while (true)
    {
        int n = epoll_wait(epfd, revs, NUM, 1000);
        switch (n)
        {
        case 0: // 超时
            cout << "time out......" << endl;
            break;
        case -1: // 出错
            cerr << "wait error" << endl;
            break;
        default: // 正常有事件就绪
            for (int i = 0; i < n; ++i)
            {
                if (revs[i].events & EPOLLIN) // 有可读事件就绪
                {
                    int sock = revs[i].data.fd;
                    if (sock == listen_sock) // 有新链接就绪
                    {
                        cout << "有新链接就绪" << endl;
                        // 将新链接加入epoll
                        epoll_event _ev;
                        int fd = Sock::Accept(listen_sock);
                        _ev.data.fd = fd;
                        _ev.events = EPOLLIN;
                        epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &_ev);
                        cout << "新链接加入epoll成功" << endl;
                    }
                    else
                    {
                        cout << "有读取事件就绪" << endl;
                        // 正常读取数据
                        char buffer[1024];
                        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
                        if (s == 0) // 对方已关闭链接
                        {
                            cout << "fd:" << revs[i].data.fd << "->链接已经关闭" << endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            cout << "后续操作处理完成" << endl;
                        }
                        else if (s > 0)
                        {
                            buffer[s] = 0;
                            cout << "client#" << buffer << endl;
                        }
                        else// 读取失败
                        {
                            cout << "fd:" << revs[i].data.fd << "->读取失败" << endl;
                            close(sock);
                            epoll_ctl(epfd, EPOLL_CTL_DEL, sock, nullptr);
                            cout << "后续操作处理完成" << endl;
                        }
                    }
                }
                else if (revs[i].events & EPOLLOUT) // 有写事件就绪
                {
                }
                else
                {
                    // 其他事件
                }
            }

            break;
        }
    }
}